package cn.xiyun.xiyuncc.service.impl;

import cn.xiyun.xiyuncc.domain.KillActivity;
import cn.xiyun.xiyuncc.domain.KillCourse;
import cn.xiyun.xiyuncc.dto.CourseKillDto;
import cn.xiyun.xiyuncc.dto.KillOrderDto;
import cn.xiyun.xiyuncc.mapper.KillCourseMapper;
import cn.xiyun.xiyuncc.service.IKillActivityService;
import cn.xiyun.xiyuncc.service.IKillCourseService;
import cn.xiyun.xiyuncc.util.AssertUtil;
import cn.xiyun.xiyuncc.util.CodeGenerateUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xiyun.maple
 * @since 2023-03-25
 */
@Service
public class KillCourseServiceImpl extends ServiceImpl<KillCourseMapper, KillCourse> implements IKillCourseService {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private IKillActivityService killActivityService;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 活动添加秒杀商品
     *
     * @param killCourse
     */
    @Override
    public void saveKillOrder(KillCourse killCourse) {
        KillActivity killActivity = killActivityService.selectById(killCourse.getActivityId());
        killCourse.setCreateTime(new Date());
        killCourse.setStartTime(killActivity.getBeginTime());
        killCourse.setEndTime(killActivity.getEndTime());
        killCourse.setTimeStr(killActivity.getTimeStr());
        killCourse.setPublishStatus(KillCourse.COURSE_TO_BE_RELEASED);
        super.insert(killCourse);
    }

    /**
     * 查询秒杀商品数据
     *
     * @return
     */
    @Override
    public List<KillCourse> onlineAll() {
        List<Object> values = redisTemplate.opsForHash().values("Activity:6");
        List<KillCourse> killCourses = JSON.parseArray(JSON.toJSONString(values), KillCourse.class);
        return killCourses;
    }

    /**
     * 查询单个秒杀商品
     *
     * @param killId
     * @param activeId
     * @return
     */
    @Override
    public KillCourse onlineOne(Long killId, Long activeId) {
        Object o = redisTemplate.opsForHash().get("Activity:" + activeId, killId.toString());
        KillCourse killCourse = JSON.parseObject(JSON.toJSONString(o), KillCourse.class);
        return killCourse;
    }

    @Override
    public String kill(CourseKillDto courseKillDto) {
        // 查询redis中是否有对应的商品数据
        KillCourse killCourse = onlineOne(courseKillDto.getKillCourseId(), courseKillDto.getActivityId());
        AssertUtil.isNotNull(killCourse, "商品不存在或商品已下线");
        // 减少信号量
        RSemaphore semaphore = redissonClient.getSemaphore(killCourse.getId().toString());
        boolean b = semaphore.tryAcquire(1);
        AssertUtil.isTrue(b, "商品已售罄");
        //TODO 获取当前登录人信息
        Long logId = 3L;
        // 设置购买信息将登陆人ID与秒杀商品ID作为key 订单号为value 存入redis 防止重复购买
        String userKillKey = logId + ":" + killCourse.getId();
        // 查询是否重复购买
        Object userKillValue = redisTemplate.opsForValue().get(userKillKey);
        AssertUtil.isNull(userKillValue, "秒杀商品每种每人限购一个");
        // 获取orderNo
        String orderNo = CodeGenerateUtils.generateOrderSn(logId);
        // 创建秒杀预订单存入redis中
        KillOrderDto killOrderDto = new KillOrderDto(
                KillOrderDto.KILL,
                logId,
                orderNo,
                killCourse.getId(),
                killCourse.getCourseId(),
                killCourse.getKillPrice());

        // 将订单号作为key将预订单数据存入redis
        redisTemplate.opsForValue().set(orderNo,killOrderDto);
        // 设置购买信息将登陆人ID与秒杀商品ID作为key 订单号为value 存入redis
        redisTemplate.opsForValue().set(userKillKey,orderNo);
        // 返回订单号
        return orderNo;
    }
}
